package com.qfmy.app.service.impl.community;

import com.qfmy.app.mapper.community.BlogMapper;
import com.qfmy.app.service.community.BlogService;
import com.qfmy.app.vo.community.BlogVo;
import com.qfmy.common.exception.BaseException;
import com.qfmy.common.login.LoginUser;
import com.qfmy.common.login.LoginUserHolder;
import com.qfmy.common.result.ResultCodeEnum;
import com.qfmy.model.entity.community.Blog;
import com.qfmy.model.entity.query.BlogQuery;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 清风明月
 * @Package com.qfmy.app.service.impl.community
 * @date 2025/4/17
 * @description 博客
 */
@Service
@SuppressWarnings("all")
public class BlogServiceImpl implements BlogService {

    /**
     * 注入mapper
     */
    @Autowired
    private BlogMapper blogMapper;
    /**
     * 注入redisTemplate
     */
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 添加博客
     * @param blogQuery
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBlog(BlogQuery blogQuery) {
        //获取用户id
        Integer userId = getUserId();
        //创建博客对象
        Blog blog = new Blog();
        //设置博客属性
        blog.setUserId(userId);
        blog.setTitle(blogQuery.getTitle());
        blog.setContent(blogQuery.getContent());
        blog.setImage(blogQuery.getImage());
        blog.setType(blogQuery.getType());
        //调用mapper添加博客
        blogMapper.insert(blog);
    }

    /**
     * 获取博客列表
     * @param pageNum
     * @param size
     * @return
     */
    @Override
    public List<BlogVo> getBlogList(Integer pageNum, Integer size) {
        //创建缓存键
        String key = generateCacheKey(pageNum,size);
        //从缓存中获取博客列表
        List<BlogVo> blogList = getListBlogByCache(key);
        //判断缓存中是否存在博客列表
        if(blogList != null) {
            return blogList;
        }
        //计算分页
        int start = getStart(pageNum,size);
        //从数据库中获取博客列表
        List<Blog> blogs = blogMapper.getBlogList(start, size);
        //拷贝数据
        blogList = CopyBlog(blogs);
        //将博客列表存入缓存并且设置过期时间为
        redisTemplate.boundValueOps(key).set(blogList,1, TimeUnit.HOURS);
        return blogList;
    }

    /**
     * 更新阅读量
     * @param blogId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateReadCount(Long blogId) {
        blogMapper.updateReadCount(blogId);
    }

    /**
     * 拷贝数据
     * @param blogList
     * @return
     */
    @Nullable
    @Contract(pure = true)
    private List<BlogVo> CopyBlog(List<Blog> blogList) {
        //判断是否存在博客列表
        if(blogList == null) {
            return null;
        }
        //创建集合
        List<BlogVo> blogVos = new ArrayList<>();
        //拷贝数据
        for (Blog blog : blogList) {
            BlogVo blogVo = new BlogVo();
            //进行对象拷贝
            BeanUtils.copyProperties(blog,blogVo);
            //获取图片
            String image = blog.getImage();
            //判断图片是否存在
            if(image != null && !image.equals("")) {
                //将图片进行分割
                String[] split = image.split(",");
                //将图片存入集合
                blogVo.setImage(split);
            }
            //将拷贝后的对象添加到集合中
            blogVos.add(blogVo);
        }
        return blogVos;
    }

    /**
     * 计算分页
     * @param pageNum
     * @param size
     * @return
     */
    private int getStart(Integer pageNum, Integer size) {
        pageNum = Math.max(pageNum, 1);
        size = Math.max(size, 15);
        return (pageNum - 1) * size;
    }

    /**
     * 从缓存中获取博客列表
     * @param key
     * @return
     */
    @Nullable
    private List<BlogVo> getListBlogByCache(String key) {
        //从缓存中获取博客列表
        BoundValueOperations<String, Object> boundValueOps = redisTemplate.boundValueOps(key);
        //判断缓存中是否存在博客列表
        if(boundValueOps.get() != null) {
            return (List<BlogVo>) boundValueOps.get();
        }
        return null;
    }

    /**
     * 生成缓存键
     * @param pageNum 当前页码
     * @param size 每页大小
     * @return 缓存键
     */
    @NotNull
    @Contract(pure = true)
    private String generateCacheKey(int pageNum, int size) {
        return String.format("novel:all:%d:%d", pageNum, size);
    }


    /**
     * 获取用户id
     * @return
     */
    @Nullable
    @Contract(pure = true)
    private Integer getUserId() {
        LoginUser loginUser = LoginUserHolder.getLoginUser();
        //判断用户是否登入
        if(loginUser == null)
        {
           throw new BaseException(ResultCodeEnum.TOKEN_INVALID);
        }
        return loginUser.getUserId();
    }
}
